import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Inject, Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { from } from 'rxjs/internal/observable/from';
import { count, filter, mapTo, mergeMap, reduce, switchMap } from 'rxjs/operators';
import { Project, User } from '../domain';

@Injectable()
export class UserService {
    private readonly domain = 'users';

    private headers = new HttpHeaders({
        'Content-Type': 'application/json',
    });

    constructor(
        private http: HttpClient,
        @Inject('BASE_CONFIG') private config
    ) { }

    searchUsers(filter: string): Observable<User[]> {
        const uri = `${this.config.uri}/${this.domain}`;
        return this.http.get<User[]>(uri, {
            params: {
                email_like: filter
            }
        })
    }

    getUsersByProject(projectId: string): Observable<User[]> {
        const uri = `${this.config.uri}/${this.domain}`;
        return this.http.get<User[]>(uri, {
            params: {
                projectId
            }
        })
    }

    addProjectRef(user: User, projectId: string): Observable<User> {

        const uri = `${this.config.uri}/${this.domain}/${user.id}`;

        const projectIds = user.projectIds || []

        if (projectIds.indexOf(projectId) > -1) {
            return of(user);
        }
        return this.http.patch<User>(uri, JSON.stringify({ projectIds: [...projectIds, projectId] }), {
            headers: this.headers,
        })
    }

    removeProjectRef(user: User, projectId: string): Observable<User> {

        const uri = `${this.config.uri}/${this.domain}/${user.id}`;

        const projectIds = user.projectIds || [];


        const index = projectIds.indexOf(projectId)

        if (index === -1) {
            return of(user);
        }

        const toUpdate = [...projectIds.slice(0, index), ...projectIds.slice(index + 1)];
        return this.http.patch<User>(uri, JSON.stringify({ projectIds: toUpdate }), {
            headers: this.headers,
        })
    }

    batchUpdateProjectRef(project: Project): Observable<User[]> {
        const projectId = project.id;
        const memberIds = project.members || [];

        return from(memberIds).pipe(
            switchMap(id => {
                const uri = `${this.config.uri}/${this.domain}/${id}`;
                return this.http.get(uri);
            }),
            filter((user: User) => user.projectIds.indexOf(projectId) < 0),
            switchMap(u => this.addProjectRef(u, projectId)),
            reduce((users, curr) => [...users, curr], [])

        )
    }
}
